# uncompyle6 version 3.2.3
# Python bytecode 3.6 (3379)
# Decompiled from: Python 3.6.8 |Anaconda custom (64-bit)| (default, Feb 21 2019, 18:30:04) [MSC v.1916 64 bit (AMD64)]
# Embedded file name: reporter\reports\developer.py
import collections
from reporter.reports.basic_template import NamedTempFileWithNormalizedWrite
from reporter.reports.basic_template import ReportTemplate
from io import StringIO
import jinja2, re


class DeveloperReport(ReportTemplate):
    REPORT_NAME = "Developer Report"

    def parts(self):
        template_loader = jinja2.FileSystemLoader(searchpath="data/templates/reports/")
        template_env = jinja2.Environment(loader=template_loader)
        common_parts_template_vars = {}
        common_parts_template = template_env.get_template("common_parts_template.html")
        template_vars = {}
        template = template_env.get_template("developer_template.html")
        data = StringIO()
        data.write(common_parts_template.render({"template_part": "header"}))
        common_parts_template_vars["template_part"] = "body_start"
        common_parts_template_vars["report_name"] = self.REPORT_NAME
        common_parts_template_vars["date_generated"] = self.get_formatted_nowdate()
        data.write(common_parts_template.render(common_parts_template_vars))
        data.seek(0)
        yield data
        data = StringIO()
        with NamedTempFileWithNormalizedWrite() as (file_summary_alerts):
            with NamedTempFileWithNormalizedWrite() as (file_scanned_items):
                with NamedTempFileWithNormalizedWrite() as (file_alerts):
                    for source in self.sources:
                        alerts_count = {3: 0, 2: 0, 1: 0, 0: 0}
                        file_summary_alerts.seek(0)
                        file_summary_alerts.truncate()
                        file_summary_alerts.write(
                            template.render({"template_part": "alerts_summary_title"})
                        )
                        file_alerts.seek(0)
                        file_alerts.truncate()
                        file_alerts.write(
                            template.render({"template_part": "alerts_details_title"})
                        )
                        file_scanned_items.seek(0)
                        file_scanned_items.truncate()
                        file_scanned_items.write(
                            template.render({"template_part": "scanned_items_title"})
                        )
                        for location in source.locations():
                            is_vulnerable = False
                            for vulnerability, _, _ in source.vulnerabilities(
                                location=location
                            ):
                                is_vulnerable = True
                                break

                            location["is_vulnerable"] = is_vulnerable
                            common_parts_template_vars["template_part"] = "scanned_item"
                            location["url"] = self.unquote_url(
                                location.get("url") or ""
                            )
                            common_parts_template_vars["location"] = location
                            file_scanned_items.write(
                                common_parts_template.render(common_parts_template_vars)
                            )

                        for vulnerability_type, cnt in source.vulnerability_types():
                            alerts_count[vulnerability_type["severity"]] += cnt
                            is_vuln_type_printed = False
                            locations = {}
                            locations_links = {}
                            for vulnerability, location, _ in source.vulnerabilities(
                                vtype=vulnerability_type
                            ):
                                if not is_vuln_type_printed:
                                    template_vars[
                                        "vulnerability_type"
                                    ] = vulnerability_type
                                    template_vars["refs"] = self.get_references(
                                        vulnerability_type["refs"],
                                        vulnerability_type["tags"],
                                    )
                                    template_vars[
                                        "severity_string"
                                    ] = self.get_severity_string(
                                        vulnerability_type["severity"]
                                    )
                                    template_vars["vuln_source"] = (
                                        vulnerability.get("source") or ""
                                    )
                                    template_vars["template_part"] = "alert"
                                    file_alerts.write(template.render(template_vars))
                                    is_vuln_type_printed = True
                                vulnerability["request"] = self.escape_html(
                                    vulnerability.get("request") or ""
                                )
                                vulnerability["location"] = location
                                template_vars["vulnerability"] = vulnerability
                                locations_links[location["path"]] = self.generate_link(
                                    location["loc_id"]
                                )
                                template_vars["link_id"] = locations_links[
                                    location["path"]
                                ]
                                template_vars["template_part"] = "affected_item_alert"
                                str_to_write = template.render(template_vars)
                                file_alerts.write(str_to_write)
                                if location["path"] not in locations:
                                    locations[location["path"]] = 0
                                locations[location["path"]] += 1

                            alert_summary_string = self.generate_alert_summary(
                                template,
                                template_vars,
                                vulnerability_type,
                                locations,
                                locations_links,
                            )
                            file_summary_alerts.write(alert_summary_string)

                        common_parts_template_vars[
                            "template_part"
                        ] = "display_scan_info"
                        common_parts_template_vars[
                            "threat_level"
                        ] = self.calculate_threat_level(alerts_count)
                        common_parts_template_vars[
                            "scan_info"
                        ] = self.get_well_formed_scan_info(source)
                        common_parts_template_vars["alerts_count"] = alerts_count
                        data.write(
                            common_parts_template.render(common_parts_template_vars)
                        )
                        data.seek(0)
                        yield data
                        data = StringIO()
                        file_summary_alerts.seek(0)
                        yield file_summary_alerts
                        file_alerts.seek(0)
                        yield file_alerts
                        file_scanned_items.seek(0)
                        yield file_scanned_items

        data.write(common_parts_template.render({"template_part": "body_end"}))
        data.seek(0)
        yield data

    def generate_alert_summary(
        self, template, template_vars, vulnerability_type, locations, locations_links
    ):
        template_vars["title"] = vulnerability_type["name"]
        template_vars["classifications"] = self.get_classifications(vulnerability_type)
        template_vars["vulnerability_type"] = vulnerability_type
        template_vars["locations"] = collections.OrderedDict(
            sorted(locations.items(), key=lambda x: x[0].lower())
        )
        template_vars["locations_links"] = locations_links
        template_vars["template_part"] = "alert_summary"
        alert_summary_string = template.render(template_vars)
        return alert_summary_string

    @staticmethod
    def get_references(references, tags):
        CVE_URL = "http://cve.mitre.org/cgi-bin/cvename.cgi?name="
        total_references = []
        total_references.extend(references)
        for tag in tags:
            if re.match("CVE-.+", tag):
                cve_reference = dict()
                cve_reference["name"] = tag
                cve_reference["url"] = CVE_URL + tag
                total_references.append(cve_reference)

        return total_references
